﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace RoutingTable
{
    public partial class F_MAIN : Form
    {
        // Define Clase    
        NODE ND         = new NODE();
        F_BS BS         = new F_BS();
        MSG  MG         = new MSG();

        NODE[] sNode = new NODE[NODE.TNODE];

		int		PATH = -1;
		int		TE	 = 50;

		int		FM = -1;
		int		CN = -1;
		int[]	mac;
		int[]	key;
		int		FRC = 0;	// Filtering Report Cnt
		int		RRC = 0;
		float	EVLT	= 0.0f;
		int		sum_hc = 0;
		int		sum_vc = 0;
		float	O_EVLT	= 0.0f;
		float	N_EVLT	= 0.0f;
		float	w = 0.7f;
		int		TNC = 0;

        public F_MAIN()
        {
            InitializeComponent();

			mac	= new int[MSG.MR];
			key = new int[MSG.MR];

			RB_SF.Checked = true;

			InitInForm();

            MakeNodes();
            WriteContentOnGird();                    
        }

		public void InitInForm()
		{
			TB_TE.Text = string.Format( "{0}", TE );
			TB_CT.Text = string.Format( "0" );
		}


        // Print a Node Information on GRID  ******************************************************
        private void BT_ND01_Click(object sender, EventArgs e)
        {
            int     id		= -9;
			string	keys	= "";

            GRID1.ClearSelection();
            id = int.Parse( ( ( Button )sender ).Text );

			keys = ND.PrtKeysofNode( sNode[id] );


            GRID1[1, 0].Value = ( ( Button )sender ).Text;          // Sensor ID
			GRID1[1, 1].Value = sNode[id].energy;                   // Sensor Energy
			GRID1[1, 2].Value = sNode[id].parentID;                 // Sensor Parent ID
			GRID1[1, 3].Value = sNode[id].hc;                       // Sensor Hop Count
			GRID1[1, 4].Value = sNode[id].vc;						// Via Count
			GRID1[1, 5].Value = sNode[id].partID;					// Partition ID
			GRID1[1, 6].Value = keys;								// Keys Print
			GRID1[1, 7].Value = ( ( Button )sender ).Location.X;	// Sensor X
            GRID1[1, 8].Value = ( ( Button )sender ).Location.Y;    // Sensor Y
            GRID1[1, 9].Value = sNode[id].distance;                 // Sensor Distance
			GRID1[1,10].Value = sNode[id].psm;						// Evaluation for PSM
			GRID1[1,11].Value = sNode[id].pdm;						// Evaluation for PDM

            PrtChildNodes( id, int.Parse(((Button)sender).Text) );
        } // private void BT_ND01_Click(object sender, EventArgs e)


        // 노드 범위 그리기    *********************************************************************
        private void BT_ND1_MouseDown(object sender, MouseEventArgs e)
        {
			int     id		= -9;
			id	= int.Parse( ( ( Button )sender ).Text );

			switch ( e.Button )
			{
				case ( MouseButtons.Right ):
					// MAC과 KEY 만들기
					GenerateReport( id );
					
					MessageBox.Show( PrtReport() );

					//ManageEnergy( id, sNode[id].hc);

					//for ( int i = 1; i < NODE.TNODE; i++ )
					//{
					//    if ( sNode[i].energy > TE )
					//        ChangePath( i );
					//}

					//EvaluateMethod();
				break;
			}
        } // private void BT_ND01_MouseDown(object sender, MouseEventArgs e)

		public string PrtReport()
		{
			string str = "";

		    for ( int i = 0; i < MSG.MR; i++ )
		        str = str + "[ mac = " + mac[i] + ", key = " + key[i] + "] ";

		    return str;			
		}

		public void MakeReport( int id )
		{
			int		idx			= 0;
			float	distance	= -1;
			int		dup			= 0;
			int[]	rn			= new int[MSG.MR];	// Range Node

			initReport();

			mac[idx] = sNode[id].partID;
			key[idx] = MG.GenerateKey( sNode[id].keyPool );
			idx++;

			// 범위 안에 있는 노드 검사
			for ( int i = 1; i < NODE.TNODE; i++ )
			{
				if ( id == i )
					continue;

				distance = ND.MeasureDistance( sNode[id].nodeX, sNode[id].nodeY, sNode[i].nodeX, sNode[i].nodeY );

				if ( distance < ( NODE.EVENT ) )
				{
					dup = MG.ChkOverlapMac( mac, sNode[i].partID );

					if ( dup != -1 )
					{
						mac[idx] = sNode[i].partID;
						key[idx] = MG.GenerateKey( sNode[i].keyPool );
						idx++;
					}
				}

				if ( idx == MSG.MR )
					break;				
			} 	
		}

		public void initReport()
		{
			for ( int i = 0; i < MSG.MR; i++ )
			{
				mac[i] = -1;			
				key[i] = -1;
			}
		}

        // 노드간 브로드캐스트    ******************************************************************
        private void BT_BC_Click(object sender, EventArgs e)
        {
			PATH = -1;
			if ( RB_RR.Checked == true )
			{
				PATH = 0;
				SearchChild();
			}
			else if ( RB_SF.Checked == true )
			{
				PATH = 1;
				SearchChild();
			}
			else if ( RB_PS.Checked == true )
			{
				PATH = 2;
				SearchChild();
				ChagePathforPSM();
				ChangePSMPath();
			}
			else if ( RB_PR.Checked == true )
			{
				PATH = 3;
				SearchChild();
			}
			else
				MessageBox.Show( "Select a used Method" );

			MeasureHC();
            
        } // private void BT_BC_Click(object sender, EventArgs e) 


        // BS 이벤트   ****************************************************************************
        private void BT_BS_Click(object sender, EventArgs e)
        {
            GRID1.ClearSelection();
            int id = 0;

            GRID1[1, 0].Value = 0;                              // Sensor ID
			GRID1[1, 1].Value = sNode[id].energy;               // Sensor Energy Consumption
			GRID1[1, 2].Value = sNode[id].parentID;             // Sensor Parent ID
			GRID1[1, 3].Value = sNode[id].hc;                   // Sensor Hop Count
			GRID1[1, 4].Value = sNode[id].vc;					// Sensor Via Count
			GRID1[1, 5].Value = sNode[id].partID;				// Sensor Partition ID
			GRID1[1, 6].Value = "-";                            // Sensor Keys
            GRID1[1, 7].Value = ( (Button)sender ).Location.X;  // Sensor X
            GRID1[1, 8].Value = ( (Button)sender ).Location.Y;  // Sensor Y		
            GRID1[1, 9].Value = 0;                              // Sensor Distance
			GRID1[1,10].Value = sNode[id].psm;					// PSM
			GRID1[1,11].Value = sNode[id].pdm;					// PDM

            PrtChildNodes( id, 0 );            
            
            // Create information for Routing Table
            for ( int i = 0; i < NODE.TNODE; i++ )
            {
                BS.nodeID[i]    = sNode[i].nodeID;
				BS.energy[i]	= sNode[i].energy;
				BS.parentID[i]	= sNode[i].parentID;
				BS.hc[i]		= sNode[i].hc;
				BS.vc[i]		= sNode[i].vc;
				BS.partID[i]	= sNode[i].partID;
				BS.keys[i]		= ND.PrtKeysofNode( sNode[i] );
                BS.nodeX[i]     = sNode[i].nodeX;
                BS.nodeY[i]     = sNode[i].nodeY;
				BS.distance[i]	= sNode[i].distance;
				BS.psm[i]		= sNode[i].psm;
				BS.pdm[i]		= sNode[i].pdm;	

                //id[i] = sNode[i].nodeID;
            }

            // Submit Variables to BSTable Form
            F_BS F = new F_BS( BS.nodeID
			                   , BS.energy
							   , BS.parentID
							   , BS.hc
							   , BS.vc
							   , BS.partID
							   , BS.keys
							   , BS.nodeX
							   , BS.nodeY
							   , BS.distance
							   , BS.psm
							   , BS.pdm 
							   , RRC
							   , EVLT );
            F.Show();
        } // private void button1_Click(object sender, EventArgs e)

        
        // Delete all things on Panel  ************************************************************
        private void BT_DEL_Click(object sender, EventArgs e)
        {
            Graphics g = PN_BG.CreateGraphics();
            g.Clear( Color.WhiteSmoke );
        } // private void BT_DEL_Click(object sender, EventArgs e)


		public int ChoosePathMethod()
		{
			int path = -1;

			if ( RB_RR.Checked == true )
				path = 0;	
			else if ( RB_SF.Checked == true )
				path = 1;
			else if ( RB_PS.Checked == true )
				path = 2;
			else if ( RB_PR.Checked == true )
				path = 3;

			return path;
		}

		public void GenerateReport( int id )
		{
			int value = -1;
			MakeReport( id );

			if ( CN != 0 )
			{
				value = MG.MakeRandom( CN );

				if ( ( 0 <= value ) && ( value < CN ) )
				{
					//허위 보고서 일 경우
					if ( FM > 0 )
					{
						for ( int r = 0; r < FM; r++ )
						{
							mac[r] = MG.ForgedReport( mac[r] );
							key[r] = MG.ForgedReport( key[r] );
						}
					}
				}
			}
		}

		// Generate Report with Repeat   **********************************************************
		// Node ID = 0, 무작위 발생
		private void BT_GN_Click(object sender, EventArgs e)
		{
			int		cnt		= 0;
			int		id		= int.Parse(TB_ND.Text);
			int		repeat  = int.Parse(TB_RP.Text);

			FM = int.Parse( TB_FM.Text );
			CN = int.Parse( TB_CN.Text );

			PATH = ChoosePathMethod();

			// 노드별 에너지 소비
			if ( id == 0 )
			{
				for ( int i = 0; i < repeat; i++ )
				{
					id = ND.ChooseNode();
					sNode[id].energy = MG.ConsumeMACGerneration( sNode[id].energy );

					GenerateReport( id );					
					ManageEnergy( id, sNode[id].hc );

					EvaluatePDM();

					N_EVLT = TotalPDM();					

					EVLT = Math.Abs(N_EVLT - O_EVLT);

					if ( PATH == 0 )
					{
						
						for ( int j = 1; j < NODE.TNODE; j++ )
						{
							if ( EVLT > TE )
							{
								ChangePath( j );
								O_EVLT = N_EVLT;
							}
						}
					}
				}
			}
			else
			{
				for ( int i = 0; i < repeat; i++ )
				{
					sNode[id].energy = MG.ConsumeMACGerneration( sNode[id].energy );

					GenerateReport( id );
					ManageEnergy( id, sNode[id].hc );

					if ( PATH == 0 )
					{
						EvaluatePDM();
						EVLT = TotalPDM();

						//TE = sum_hc + sum_vc;

						for ( int j = 1; j < NODE.TNODE; j++ )
						{
							if ( EVLT > TE )
								ChangePath( j );
						}
					}
				}
			}

			if ( PATH == 3 )
			{
				for ( int i = 1; i < NODE.TNODE; i++ )
					ChangePath( i );
			}						    

			//EvaluateMethod();
			MeasureHC();

			cnt = int.Parse(TB_CT.Text) + repeat;			
			TB_CT.Text = string.Format( "{0}", cnt);
			TB_TE.Text = string.Format( "{0}", TE );
			TB_EV.Text = string.Format( "{0}", EVLT );
			TB_RR.Text = string.Format( "{0}", RRC );
			TB_TN.Text = string.Format( "{0}", TNC );

			//MessageBox.Show( string.Format( "{0}", ReRouting ) );
		} // private void BT_GN_Click(object sender, EventArgs e)

		
		public void ChangePSMPath()
		{
			for ( int i = 1; i < NODE.TNODE; i++ )
			{
				int id = ChangePath( i );	
			}
		}


		// Chage Path if distance is less than NODE.RANGE	***************************************
		// int id is ID of a Node that is less than Threshold Energy
		public int ChangePath( int id )
		{
			int		idx			= 0;
			float	distance	= -1;
			int[]	rn			= new int[NODE.RANGE/5];	// Range Node
			int		c_id		= -1;

			// 범위 안에 있는 노드 검사
			for ( int i = 1; i < NODE.TNODE; i++ )
			{
				if ( id == i )
					continue;

				distance = ND.MeasureDistance( sNode[id].nodeX, sNode[id].nodeY, sNode[i].nodeX, sNode[i].nodeY );

				if ( distance < ( NODE.RANGE ) )
				{
					rn[idx] = i;
					idx++;
				}
			} 
			
			// 범위 안에 있는 노드 상태 검사
			c_id = CommonEvaluation( rn );			

			if ( ( sNode[id].parentID != c_id ) && ( c_id > -1 ) )
			{
				// PRM에서 무조건 새 부모 노드는 기존 부모 노드보다 홉 수가 작아야 한다.
				if ( PATH == 3 )
				{
					if ( sNode[id].hc > sNode[c_id].hc )
						ChangeNodeInformation( id, c_id );
				}
				else
				{
					ChangeNodeInformation( id, c_id );
				}
				return c_id;
			}

			return -1;			
		} // public void ChangePath( int id )


		// Evaluate Common by only Hop Count ******************************************************
		public int CommonEvaluation( int[] rn )
		{
			int	id	= -9;
			int min = Int32.MaxValue;
			int min1 = Int32.MaxValue;

			for ( int i = 0; i < rn.Length; i++ )
			{
				if( rn[i] > 0 )
				{
					switch ( PATH )
					{
						case 0:
							if ( ( min > sNode[rn[i]].pdm ) && ( min1 > sNode[rn[i]].hc ) )
							{
								min = ( int )sNode[rn[i]].pdm;
								min1 = ( int )sNode[rn[i]].hc;
								id  = sNode[rn[i]].nodeID;
							}
							break;
						case 2:
							if ( min > sNode[rn[i]].psm )
							{
								min = ( int )sNode[rn[i]].psm;
								id  = sNode[rn[i]].nodeID;
							}
							break;
						case 3:
							if ( ( min > sNode[rn[i]].energy ) && ( min1 > sNode[rn[i]].hc ) )
							{
								min  = ( int )sNode[rn[i]].energy;
								min1 = ( int )sNode[rn[i]].hc;
								id = sNode[rn[i]].nodeID;
							}
							break;							
					}
				}
			}

			return id;
		} // public int CommonEvaluation( int[] rn )

		// Change Information of a Node	***********************************************************
		// int id is ID of a Node that is less than Threshold Energy
		// int c_id is a Changed ID by main Hop Count.
		public void ChangeNodeInformation( int id, int c_id )
		{
			bool chk = true;

			if ( PATH == 3 )
			{
				for ( int i = 0; i < NODE.CHLD; i++ ) 
				{
					if ( sNode[id].child[i] == c_id	)
						chk = false;
				}
				if ( chk == true )
				{
					sNode[id].parentID = c_id;
					DecideChildNode();
					DrawLineBetweenNodes( PATH, sNode[id].nodeX, sNode[id].nodeY, sNode[c_id].nodeX, sNode[c_id].nodeY );
				}
			}
			else
			{
				int diff = sNode[id].hc - sNode[c_id].hc;
				if ( diff >= NODE.LMTHC )
				{
					sNode[id].parentID = c_id;
					DecideChildNode();
					DrawLineBetweenNodes( PATH, sNode[id].nodeX, sNode[id].nodeY, sNode[c_id].nodeX, sNode[c_id].nodeY );
				}
			}
		} // public void ChangeNodeInformation( int id, int c_id )


        // 노드 연결하기  **************************************************************************
		// B is True : First Path
		//      False: Changed Path
        public void DrawLineBetweenNodes( int color, float x1, float y1, float x2, float y2 )
        {
			switch( color )
			{
				case 0:
					Pen rr = new Pen( Color.Red, 2 );
					Graphics g_rr = PN_BG.CreateGraphics();
					g_rr.DrawLine( rr, x1, y1, x2, y2 );
					break;
				case 2:
					Pen psm = new Pen( Color.Brown, 2 );
					Graphics g_psm = PN_BG.CreateGraphics();
					g_psm.DrawLine( psm, x1, y1, x2, y2 );
					break;
				case 3:
					Pen prm = new Pen( Color.Blue, 2 );
					Graphics g_prm = PN_BG.CreateGraphics();
					g_prm.DrawLine( prm, x1, y1, x2, y2 );
					break;
				case 9:
					Pen p = new Pen( Color.Gray, 1 );
					Graphics g = PN_BG.CreateGraphics();
					g.DrawLine( p, x1, y1, x2, y2 );
					break;
			}
        } // public void DrawLineBetweenNodes


        // 자식 노드 검색 **************************************************************************
        public void SearchChild()
        {
            // Search Whole Nodes
            for ( int i = 0; i < NODE.TNODE; i++ )
            {
                // Search Child Nodes of a node
                for ( int c = 0; c < NODE.CHLD; c++ )
                {
                    int chd = -1;

                    // Match NodeID and Child Nodes
                    for ( int j = 0; j < NODE.TNODE; j++ )
                    {
                        if ( sNode[i].child[c].Equals(0) )
                            continue;

                        if ( sNode[j].nodeID == sNode[i].child[c] )
                        {
                            chd = sNode[i].child[c];
                            DrawLineBetweenNodes( 9, sNode[i].nodeX, sNode[i].nodeY, sNode[chd].nodeX, sNode[chd].nodeY );
                            break;
                        }
                    } // the End of Match NodeID and Child Nodes
                } // the End of Search Child Nodes of a node
            } // the End of Search Whole Nodes
        } // public void public void SearchChild()


        // 센서네트워크 인스턴스화   ****************************************************************
        public void MakeNodes()
        {
            for (int i = 0; i < NODE.TNODE; i++)
            {
                sNode[i] = new NODE();
                sNode[i].nodeID = i;

				// Exclude BaseStation Because of already having its Information.
				if ( i != 0 )
				{
					Control[] ctrl = this.Controls.Find("BT_ND" + i, true);

					if ( 0 < ctrl.Length )
					{
						sNode[i].nodeX = ctrl[0].Location.X;
						sNode[i].nodeY = ctrl[0].Location.Y;
						//MessageBox.Show(string.Format("{0} {1}", sNode[i].nodeX, sNode[i].nodeY));
					}

					// Calculate Distance between nodes
					sNode[i].distance = ND.MeasureDistance( F_BS.BS_X
														    , F_BS.BS_Y
															, sNode[i].nodeX
															, sNode[i].nodeY);

					ND.DistributeKeys( sNode[i] );
				}
            }
            
            // Create Base Station
            BS.MakeBS( sNode[0] );
            
            DecideParentNode();
            MeasureHC();
        } // public void MakeNodes()


        // Measure Hop Count    *******************************************************************
        public void MeasureHC()
        {
			for ( int i = 0; i < NODE.TNODE; i++ )
				sNode[i].hc = 0;

            for( int i = 1; i < NODE.TNODE; i++ )
            {
                int tmp = i;
                int hop = 0;

                while( sNode[tmp].parentID != -1 )
                {
                    tmp = sNode[tmp].parentID;
                    hop++;

                    if ( hop > F_BS.LMT_HC )
                        break;                    
                }
                sNode[i].hc = hop;                    
            }    
        } // public void MeasureHC()

        
        // Make Contents on GRID    ***************************************************************
        public void WriteContentOnGird()
        {
            GRID1.Rows.Add(11);
            GRID1[0, 0].Value = "Node ID";
			GRID1[0, 1].Value = "Energy";
			GRID1[0, 2].Value = "Parent ID";
			GRID1[0, 3].Value = "Hop Count";
			GRID1[0, 4].Value = "Via Count";
			GRID1[0, 5].Value = "Partition ID";
			GRID1[0, 6].Value = "Key";
			GRID1[0, 7].Value = "Node X";
            GRID1[0, 8].Value = "Node Y";
            GRID1[0, 9].Value = "Distance";
			GRID1[0,10].Value = "PSM";
			GRID1[0,11].Value = "PDM";
        } // public void WriteContentOnGird()


        // Print Child Nodes on GRID    ***********************************************************
        public void PrtChildNodes( int id, int bs )
        {
            GRID2.ClearSelection();
            GRID2.RowCount = 1;
            GRID2.Rows.Add(sNode[id].child.Length - 1);

            for (int i = 0; i < sNode[id].child.Length; i++)
            {
                if ( !sNode[id].child[i].Equals(0) )
                {
                    GRID2[0, i].Value = i;
                    GRID2[1, i].Value = sNode[id].child[i];
                }
            }
        } // public void PrtChildNodes( int id, int bs )


        // Set Child Nodes  ***********************************************************************
        public void DecideChildNode()
        {
			for (int n = 0; n < NODE.TNODE; n++)
            {
				Array.Clear( sNode[n].child, 0, NODE.CHLD );
			}

            for (int n = 0; n < NODE.TNODE; n++)
            {
                int ch = 0;
                for (int p = 1; p < NODE.TNODE; p++)
                {
                    if ( sNode[n].nodeID == sNode[p].parentID )
                    {
                        sNode[n].child[ch] = sNode[p].nodeID;
                        ch++;
                    }
                }
            }
        } // public void DecideChildNode()    


        // Sum Each Energy of Node  ***************************************************************
        public void ManageEnergy( int id, int hc )
        {
            for ( int i = 0; i <= hc; i++ )
            {
				sNode[id].vc++;
                sNode[id].energy = MG.ConsumeForTransmission( sNode[id].energy );

				if ( MG.ChkForgedMAC( mac, sNode[id].partID ) )
				{
					FRC++;
					break;

					//if ( MG.ChkForgedKey( key, sNode[id].keyPool ) )
					//{
					//    FRC++;
					//    break;
					//}
				}
				TNC++;
				

                id = sNode[id].parentID;

				if ( id == -1 )
				{
					RRC++;
					break;
				}

                sNode[id].energy = MG.ConsumeForReceiption( sNode[id].energy );
            }

			// Initial Energy of BS because of having infinite Energy.
            BS.InitBSEnergy( sNode[0] );

			TB_FT.Text = string.Format( "{0}", FRC );
        }  // public void ManageEnergy( int id )


		// Sum Each Energy of Node For PRM  *************************************************************
		public void ManageEnergyForPRM( int id )
		{
			int idx = -1;
			for ( int i = 0; i <= id; i++ )
			{
				sNode[id].energy = MG.ConsumeForTransmission( sNode[id].energy );
				id = sNode[id].parentID;

				if ( sNode[id].energy > MSG.PRM_TE )
				{
					idx = ChangePath( id );
					if ( idx != -1 )
					{
						sNode[idx].energy = MG.ConsumeForReceiption( sNode[idx].energy );
						id = idx;
					}
					else
						sNode[id].energy = MG.ConsumeForReceiption( sNode[id].energy );
				}
				else
					sNode[id].energy = MG.ConsumeForReceiption( sNode[id].energy );
				sNode[id].vc++;
			}

			// Initial Energy of BS because of having infinite Energy.
			BS.InitBSEnergy( sNode[0] );
		}  // public void ManageEnergyForPRM(int id)

		public void EvaluatePDM()
		{
			//int		pid		= 1;			
			//int		sumtr	= 0;
			//int		sumhc	= 0;
			//float	sumce	= 0.0f;
			
			
			for ( int i = 1; i < NODE.TNODE; i++ )
			{
				float NE = 0.0f;
				//pid = i;
				//for ( int j = 0; j < MSG.THC; j++ )
				//{
				//    if ( pid == -1 )
				//        break;

				//    //sumce = sumce + sNode[pid].energy;
				//    sumtr = sumtr + sNode[pid].vc;
				//    sumhc = sumhc + sNode[pid].hc;

				//    pid = sNode[pid].parentID;
				//}
				

				NE = (float)(sNode[i].vc*100) / RRC;
				sNode[i].pdm = NE + sNode[i].hc;
			}
		}

		public float TotalPDM()
		{
			float sum = 0.0f;

			sum_hc = 0;
			sum_vc = 0;

			for ( int i = 1; i < NODE.TNODE; i++ )
			{
				sum = sum + sNode[i].pdm;

				sum_hc = sum_hc + sNode[i].hc;
				sum_vc = sum_vc + sNode[i].vc;
			}
			
			return sum * w;
		}


		// Evaluate Each Mehtod for the Fuction	***************************************************
		public void EvaluateMethod()
		{
			double	result	= 0.0;
			int		sumtr	= 0;
			int		sumhc	= 0;

			for ( int i = 1; i < NODE.TNODE; i++ )
			{
				sumtr = sumtr + sNode[i].vc;
				sumhc = sumhc + sNode[i].hc;
			}

			result = MG.CalculatePDM( sumtr, RRC, sumhc );
			//if ( result > 100 )
			//{
			//    MessageBox.Show( string.Format( "{0}", result ) );
			//}
		} // public void EvaluateMethod()


		// Path Selection Method할 노드 검사	*******************************************************
		public void ChagePathforPSM()
		{
			for ( int i = 1; i < NODE.TNODE; i++ )
			{
				sNode[i].psm = CalculatePSM( sNode[i].nodeID, sNode[i].hc );
			}
		} // public void ChagePathforPSM()

		// Path Selection Method 결정	***********************************************************
		public float CalculatePSM( int id, int hc )
		{
			int cid = id;
			ArrayList pik = new ArrayList();
			pik.Clear();

			for ( int i = 0; i < hc; i++ )
			{
				if ( !( pik.Contains( sNode[cid].partID ) ) )
				{
					pik.Add( sNode[id].partID );
					cid = sNode[id].parentID;
				}
			}

			return ( sNode[id].hc + ( NODE.PSM_W * pik.Count ) );
		} // public float CalculatePSM( int id, int hc )


		// Set Parent Node  ***********************************************************************
		public void DecideParentNode()
        {
            sNode[1].parentID  = 0;
            sNode[2].parentID  = 0;
            sNode[3].parentID  = 0;
            sNode[4].parentID  = 3;
            sNode[5].parentID  = 4;
            sNode[6].parentID  = 7;
            sNode[7].parentID  = 9;
            sNode[8].parentID  = 7;
            sNode[9].parentID  = 0;
            sNode[10].parentID = 9;

            sNode[11].parentID = 12;
            sNode[12].parentID = 1;
            sNode[13].parentID = 12;
            sNode[14].parentID = 2;
            sNode[15].parentID = 2;
            sNode[16].parentID = 3;
            sNode[17].parentID = 3;
            sNode[18].parentID = 19;
            sNode[19].parentID = 5;
            sNode[20].parentID = 5;

            sNode[21].parentID = 41;
            sNode[22].parentID = 43;
            sNode[23].parentID = 24;
            sNode[24].parentID = 10;
            sNode[25].parentID = 26;
            sNode[26].parentID = 11;
            sNode[27].parentID = 26;
            sNode[28].parentID = 13;
            sNode[29].parentID = 28;
            sNode[30].parentID = 31;

            sNode[31].parentID = 32;
            sNode[32].parentID = 15;
            sNode[33].parentID = 16;
            sNode[34].parentID = 33;
            sNode[35].parentID = 34;
            sNode[36].parentID = 17;
            sNode[37].parentID = 18;
            sNode[38].parentID = 39;
            sNode[39].parentID = 40;
            sNode[40].parentID = 41;

            sNode[41].parentID = 195;
            sNode[42].parentID = 43;
            sNode[43].parentID = 44;
            sNode[44].parentID = 23;
            sNode[45].parentID = 23;
            sNode[46].parentID = 25;
            sNode[47].parentID = 25;
            sNode[48].parentID = 26;
            sNode[49].parentID = 27;
			sNode[50].parentID = 28;

			sNode[51].parentID = 29;
			sNode[52].parentID = 30;
			sNode[53].parentID = 54;
			sNode[54].parentID = 32;
			sNode[55].parentID = 56;
			sNode[56].parentID = 57;
			sNode[57].parentID = 58;
			sNode[58].parentID = 35;
			sNode[59].parentID = 58;
			sNode[60].parentID = 90;

			sNode[61].parentID = 62;
			sNode[62].parentID = 38;
			sNode[63].parentID = 64;
			sNode[64].parentID = 65;
			sNode[65].parentID = 125;
			sNode[66].parentID = 43;
			sNode[67].parentID = 95;
			sNode[68].parentID = 46;
			sNode[69].parentID = 46;
			sNode[70].parentID = 71;

			sNode[71].parentID = 47;
			sNode[72].parentID = 73;
			sNode[73].parentID = 48;
			sNode[74].parentID = 49;
			sNode[75].parentID = 74;
			sNode[76].parentID = 104;
			sNode[77].parentID = 51;
			sNode[78].parentID = 51;
			sNode[79].parentID = 80;
			sNode[80].parentID = 52;

			sNode[81].parentID = 82;
			sNode[82].parentID = 83;
			sNode[83].parentID = 54;
			sNode[84].parentID = 55;
			sNode[85].parentID = 56;
			sNode[86].parentID = 56;
			sNode[87].parentID = 59;
			sNode[88].parentID = 87;
			sNode[89].parentID = 60;
			sNode[90].parentID = 91;

			sNode[91].parentID = 62;
			sNode[92].parentID = 63;
			sNode[93].parentID = 92;
			sNode[94].parentID = 131;
			sNode[95].parentID = 133;
			sNode[96].parentID = 135;
			sNode[97].parentID = 69;
			sNode[98].parentID = 70;
			sNode[99].parentID = 72;
			sNode[100].parentID = 101;

			sNode[101].parentID = 73;
			sNode[102].parentID = 74;
			sNode[103].parentID = 102;
			sNode[104].parentID = 103;
			sNode[105].parentID = 106;
			sNode[106].parentID = 78;
			sNode[107].parentID = 78;
			sNode[108].parentID = 79;
			sNode[109].parentID = 110;
			sNode[110].parentID = 82;

			sNode[111].parentID = 110;
			sNode[112].parentID = 111;
			sNode[113].parentID = 152;
			sNode[114].parentID = 85;
			sNode[115].parentID = 86;
			sNode[116].parentID = 88;
			sNode[117].parentID = 116;
			sNode[118].parentID = 119;
			sNode[119].parentID = 120;
			sNode[120].parentID = 90;

			sNode[121].parentID = 120;
			sNode[122].parentID = 159;
			sNode[123].parentID = 93;
			sNode[124].parentID = 65;
			sNode[125].parentID = 126;
			sNode[126].parentID = 197;
			sNode[127].parentID = 195;
			sNode[128].parentID = 196;
			sNode[129].parentID = 42;
			sNode[130].parentID = 66;

			sNode[131].parentID = 198;
			sNode[132].parentID = 133;
			sNode[133].parentID = 94;
			sNode[134].parentID = 133;
			sNode[135].parentID = 97;
			sNode[136].parentID = 98;
			sNode[137].parentID = 99;
			sNode[138].parentID = 100;
			sNode[139].parentID = 101;
			sNode[140].parentID = 103;

			sNode[141].parentID = 103;
			sNode[142].parentID = 143;
			sNode[143].parentID = 105;
			sNode[144].parentID = 107;
			sNode[145].parentID = 108;
			sNode[146].parentID = 145;
			sNode[147].parentID = 109;
			sNode[148].parentID = 149;
			sNode[149].parentID = 150;
			sNode[150].parentID = 111;

			sNode[151].parentID = 150;
			sNode[152].parentID = 151;
			sNode[153].parentID = 114;
			sNode[154].parentID = 115;
			sNode[155].parentID = 117;
			sNode[156].parentID = 118;
			sNode[157].parentID = 119;
			sNode[158].parentID = 159;
			sNode[159].parentID = 121;
			sNode[160].parentID = 122;

			sNode[161].parentID = 122;
			sNode[162].parentID = 132;
			sNode[163].parentID = 132;
			sNode[164].parentID = 135;
			sNode[165].parentID = 135;
			sNode[166].parentID = 136;
			sNode[167].parentID = 137;
			sNode[168].parentID = 167;
			sNode[169].parentID = 138;
			sNode[170].parentID = 169;

			sNode[171].parentID = 138;
			sNode[172].parentID = 171;
			sNode[173].parentID = 171;
			sNode[174].parentID = 173;
			sNode[175].parentID = 172;
			sNode[176].parentID = 172;
			sNode[177].parentID = 141;
			sNode[178].parentID = 148;
			sNode[179].parentID = 178;
			sNode[180].parentID = 179;

			sNode[181].parentID = 186;
			sNode[182].parentID = 152;
			sNode[183].parentID = 184;
			sNode[184].parentID = 185;
			sNode[185].parentID = 181;
			sNode[186].parentID = 182;
			sNode[187].parentID = 190;
			sNode[188].parentID = 186;
			sNode[189].parentID = 190;
			sNode[190].parentID = 153;

			sNode[191].parentID = 154;
			sNode[192].parentID = 155;
			sNode[193].parentID = 173;
			sNode[194].parentID = 173;
			sNode[195].parentID = 196;
			sNode[196].parentID = 129;
			sNode[197].parentID = 39;
			sNode[198].parentID = 130;
			sNode[199].parentID = 130;

            DecideChildNode();
        } // public void DecideParentNode()		
    } // the end of class    
}
